1 00:00:00,430 --> 00:00:01,180 Welcome. 2 00:00:01,180 --> 00:00:06,580 In this lecture, we're going to be learning about the pathfinding service, which allows you to move 3 00:00:06,580 --> 00:00:12,010 a humanoid character rig towards a desired destination along a computed path. 4 00:00:12,010 --> 00:00:13,510 So let's get started. 5 00:00:14,300 --> 00:00:18,590 Now I'm going to be using this little setup area I've got here to demonstrate the pathfinding service. 6 00:00:18,590 --> 00:00:22,580 If you would like to use the same setup that I have here, then I will have this model attached to the 7 00:00:22,580 --> 00:00:24,230 lecture for you to use. 8 00:00:24,230 --> 00:00:28,640 Otherwise we can head to the avatar tab and create a new AR 15 rig. 9 00:00:28,640 --> 00:00:33,200 I'll just make a block avatar and this guy is going to act as our AI. 10 00:00:33,230 --> 00:00:38,630 So inside of him we can go ahead and create a new server script that's going to move him around along 11 00:00:38,630 --> 00:00:40,130 a computed path. 12 00:00:41,040 --> 00:00:44,490 Of course, one of the first things we're going to need is the pathfinding service. 13 00:00:44,490 --> 00:00:45,390 So we'll make a variable. 14 00:00:45,390 --> 00:00:50,460 We'll call it pathfinding service and that's equal to game get service pathfinding service. 15 00:00:50,700 --> 00:00:54,510 Then we can go ahead and refer to the rig which is script dot parent. 16 00:00:54,510 --> 00:00:58,290 We'll get his humanoid which is equal to rig dot humanoid. 17 00:00:58,290 --> 00:01:03,900 And then we also want to get the goal part that I have in the workspace that we want our rig to move 18 00:01:03,900 --> 00:01:05,910 to, which is this part right here. 19 00:01:05,910 --> 00:01:08,130 So we'll make a reference to this goal part. 20 00:01:08,130 --> 00:01:10,470 And that's in my workspace dot goal. 21 00:01:11,170 --> 00:01:17,170 Now inside of the pathfinding service there is a function called create path, and this returns to us 22 00:01:17,170 --> 00:01:18,370 a path instance. 23 00:01:18,370 --> 00:01:24,790 And we can use this path instance to compute paths around our map from a starting point and an ending 24 00:01:24,790 --> 00:01:30,820 point, and we can pass to this function something called agent parameters, which is a table that gives 25 00:01:30,820 --> 00:01:34,990 us some customization of how we would like this path to be computed. 26 00:01:35,440 --> 00:01:41,620 So what I'm going to do is I'm going to create a new table and I'm going to call it my agent params. 27 00:01:42,190 --> 00:01:46,150 And we're going to pass agent params to my create path function. 28 00:01:46,940 --> 00:01:51,770 Now, inside of this table, we have access to several different properties to manipulate how we want 29 00:01:51,770 --> 00:01:53,180 this path to behave. 30 00:01:53,180 --> 00:01:56,540 For example, one of the first ones is called Agent Radius. 31 00:01:57,690 --> 00:02:03,960 And this defines the minimum amount of horizontal space required to be considered traversable for our 32 00:02:03,960 --> 00:02:04,560 humanoid. 33 00:02:04,560 --> 00:02:09,180 So this value should be half the width of your character at minimum. 34 00:02:09,570 --> 00:02:15,690 And that's because if you were to set this value to something like 0.5, well, clearly the width of 35 00:02:15,690 --> 00:02:20,370 our character is not going to be one stud or 0.5 radius. 36 00:02:20,370 --> 00:02:25,890 And because of that, our rig is not going to be able to traverse through spaces that have a width of 37 00:02:25,890 --> 00:02:29,400 one stud, because the total width of our character is not one stud. 38 00:02:29,400 --> 00:02:34,440 In fact, our humanoid root part, which is the area that's going to be colliding, has a width of two 39 00:02:34,440 --> 00:02:34,950 studs. 40 00:02:34,950 --> 00:02:40,980 So at minimum, this value should be half the width of your humanoid root part. 41 00:02:40,980 --> 00:02:46,410 So we can go ahead and refer to our rig, get the humanoid root part, get it size on the x axis and 42 00:02:46,410 --> 00:02:48,150 divide it by two to get the radius. 43 00:02:48,150 --> 00:02:50,160 So that's going to be our agent radius. 44 00:02:50,160 --> 00:02:53,940 The next property is going to be called agent height. 45 00:02:53,940 --> 00:02:59,940 And this is the same thing as agent Radius except it defines the minimum amount of vertical space required 46 00:02:59,940 --> 00:03:02,460 to be considered traversable for our humanoid. 47 00:03:02,880 --> 00:03:06,120 So default humanoid rigs are about five studs in height. 48 00:03:06,120 --> 00:03:13,500 So we want to make sure that we set this height value to be at least the height of our AI rig. 49 00:03:13,950 --> 00:03:15,720 So I'm going to set it to five. 50 00:03:15,930 --> 00:03:19,170 The next property is called Agent Can Jump. 51 00:03:19,170 --> 00:03:25,380 And this allows us to tell the pathfinding service if it's okay for our AI to jump at certain areas 52 00:03:25,380 --> 00:03:27,390 in a path to reach the destination. 53 00:03:27,390 --> 00:03:33,990 So for example, here along this route, clearly our rig is going to have to jump over this gap and 54 00:03:33,990 --> 00:03:35,310 jump over this gap. 55 00:03:35,310 --> 00:03:42,060 If we do not set this to true, then our AI is going to avoid going this way because our AI can't jump. 56 00:03:42,060 --> 00:03:46,500 So it's going to try and find a different way to get to our point right here. 57 00:03:46,740 --> 00:03:49,770 But I'm going to set agent can jump equal to true. 58 00:03:49,770 --> 00:03:53,250 And then the next property is called agent can climb. 59 00:03:53,250 --> 00:03:57,900 And this allows us to tell the pathfinding service if it's okay for our AI to climb. 60 00:03:57,900 --> 00:03:58,980 Trust parts. 61 00:03:58,980 --> 00:04:05,790 So for example if our agent can't jump, but let's say he can climb a trust part, then he'll path find 62 00:04:05,790 --> 00:04:09,180 and climb up this trust part to reach to our point. 63 00:04:09,180 --> 00:04:11,790 So we're going to set this to false for now. 64 00:04:12,600 --> 00:04:18,960 And then the next property is called waypoint spacing, and this allows us to control how detailed we 65 00:04:18,960 --> 00:04:20,190 would like the path to be. 66 00:04:20,190 --> 00:04:26,190 The number that we pass here is going to represent the spacing and studs between waypoints along a path. 67 00:04:26,190 --> 00:04:31,530 For example, a value of four would mean that each waypoint has a distance of four studs in between 68 00:04:31,530 --> 00:04:38,670 them, while a value of like 0.5 would mean each waypoint has a distance of 0.5 studs between them, 69 00:04:38,670 --> 00:04:45,150 so you'll have a lot more waypoints with a smaller waypoint spacing, which makes your path more detailed. 70 00:04:45,630 --> 00:04:48,750 But I'm going to set this value at the default of four. 71 00:04:48,900 --> 00:04:54,870 And then the last parameter we can go ahead and define in here is going to be a table called costs. 72 00:04:55,560 --> 00:05:02,340 And what this has to be is a dictionary that contains key value pairs, and the keys must be the name 73 00:05:02,340 --> 00:05:08,820 of either materials or the labels of pathfinding modifiers in our game. 74 00:05:08,820 --> 00:05:15,510 And then you can assign a value to those keys to represent the cost of your AI traversing through that 75 00:05:15,510 --> 00:05:21,210 specific material, or a specific part that has a pathfinding modifier inside of it. 76 00:05:21,210 --> 00:05:27,180 So if the cost is very high, then the pathfinding service will try to compute a path to avoid walking 77 00:05:27,180 --> 00:05:30,210 over that specific material as much as possible. 78 00:05:30,210 --> 00:05:38,670 For example, if I don't want my AI to walk over the material of cracked lava, then to have my AI completely 79 00:05:38,670 --> 00:05:43,710 avoid the material of cracked lava, then I can set the value equal to math dot huge. 80 00:05:43,710 --> 00:05:48,270 And this means my AI will never, ever compute a path over this material. 81 00:05:48,870 --> 00:05:52,200 You also heard me talk about pathfinding modifiers earlier. 82 00:05:52,410 --> 00:05:56,970 So if I were to go to this part, I actually already have a pathfinding modifier in here, but I'll 83 00:05:56,970 --> 00:05:58,140 just create another one. 84 00:05:58,140 --> 00:06:03,090 So we'll create and add a new pathfinding modifier as a child of this part. 85 00:06:03,090 --> 00:06:06,630 And here we can give a label for this pathfinding modifier. 86 00:06:06,630 --> 00:06:10,530 I'm going to call this my avoid part. 87 00:06:10,530 --> 00:06:15,780 And I don't want my AI to be able to walk or traverse over this particular part. 88 00:06:15,780 --> 00:06:21,840 So that means inside of my cost table, I can go ahead and refer to the label that I gave to this pathfinding 89 00:06:21,840 --> 00:06:23,400 modifier, which is avoid part. 90 00:06:23,400 --> 00:06:26,850 And I can also set its value equal to math dot huge. 91 00:06:26,850 --> 00:06:30,930 And now my AI is never ever going to walk over that part. 92 00:06:31,650 --> 00:06:37,110 So now that we have our agent parameters set up, this function is going to return to us a path instance. 93 00:06:37,110 --> 00:06:40,680 So I'll store it in a variable, I'll call it my path. 94 00:06:40,800 --> 00:06:44,820 And then for the sake of this lecture I'm going to type annotate it as a path. 95 00:06:44,820 --> 00:06:48,120 So we get access to all of the autofill features. 96 00:06:48,120 --> 00:06:52,860 You don't have to worry about type annotation, but I'm just going to do this for the sake of the lecture. 97 00:06:53,040 --> 00:06:55,680 And now what we can go ahead and do is refer to this path. 98 00:06:55,680 --> 00:07:01,260 And there's a function inside of it called compute async and it says computes a path from a start point 99 00:07:01,260 --> 00:07:02,700 to an end position. 100 00:07:02,700 --> 00:07:05,550 The starting position would be the position of our humanoid. 101 00:07:05,550 --> 00:07:09,030 So we would do rig dot humanoid route part. 102 00:07:09,950 --> 00:07:11,000 That position. 103 00:07:12,420 --> 00:07:15,660 And then the end goal is going to be our goal parts position. 104 00:07:15,660 --> 00:07:18,300 So we'll get our goal and pass the position. 105 00:07:18,630 --> 00:07:23,310 Once it computes the path, then it's going to tell us whether or not it was successful. 106 00:07:23,310 --> 00:07:27,270 So inside of our path we also have another property called status. 107 00:07:27,270 --> 00:07:29,790 And it says the success of the generated path. 108 00:07:29,790 --> 00:07:36,780 So if the status is equal to the enum dot path status dot success, then that means it has successfully 109 00:07:36,780 --> 00:07:39,000 generated a path for us to use. 110 00:07:39,000 --> 00:07:41,220 So we're going to check if we were successful. 111 00:07:41,220 --> 00:07:45,600 And if we did, then this is where we're going to loop through every single waypoint that was generated 112 00:07:45,600 --> 00:07:49,320 by our path, and move our humanoid along those waypoints. 113 00:07:49,320 --> 00:07:55,590 Otherwise, if we were not successful, then we can warn and say something like fail to compute path, 114 00:07:55,590 --> 00:07:59,970 and then we can go ahead and print out what the status is in the console. 115 00:07:59,970 --> 00:08:05,340 Otherwise, what we can go ahead and do is we can loop through every single waypoint that is inside 116 00:08:05,340 --> 00:08:10,710 of our path, and we can get those waypoints because our path has a function called get waypoints and 117 00:08:10,710 --> 00:08:14,130 it says returns an array of points in the path. 118 00:08:14,520 --> 00:08:20,160 And I'm also going to type annotate this as well to declare as a path waypoint. 119 00:08:21,690 --> 00:08:27,060 And this point has a couple of properties inside of it that defines the position, as well as the action 120 00:08:27,060 --> 00:08:28,920 to perform for the humanoid. 121 00:08:29,560 --> 00:08:35,560 So, for example, some of our waypoints are going to notify us that we need to jump over a gap. 122 00:08:35,560 --> 00:08:44,410 So that means the point dot action is going to be set equal to the enum dot waypoint action path waypoint 123 00:08:44,410 --> 00:08:45,730 action dot jump. 124 00:08:45,820 --> 00:08:51,940 So if the action we need to perform is to jump, then we want to force our humanoid to jump. 125 00:08:51,940 --> 00:08:53,230 And that's very easy to do. 126 00:08:53,260 --> 00:08:56,470 We can set the humanoid dot jump property equal to true. 127 00:08:56,980 --> 00:09:02,860 However, before we have our humanoid jump, we obviously want to move them towards the position of 128 00:09:02,860 --> 00:09:03,760 this waypoint. 129 00:09:03,760 --> 00:09:09,460 So inside of our humanoid we have a function called move two and it says causes the humanoid to attempt 130 00:09:09,460 --> 00:09:10,990 to walk to the given location. 131 00:09:10,990 --> 00:09:15,190 By setting the humanoid walk to point and humanoid walk two part properties. 132 00:09:15,880 --> 00:09:21,280 So the location we want the humanoid to move to is going to be our point dot position. 133 00:09:22,060 --> 00:09:24,580 So then our humanoid is going to move to this position. 134 00:09:24,580 --> 00:09:27,670 If we need to jump, we're going to force our humanoid to jump. 135 00:09:27,670 --> 00:09:32,830 And then what we need to do is we need to wait for our humanoid to actually make it to this position. 136 00:09:32,830 --> 00:09:38,470 If we don't put a yield statement in here, then this for loop is going to basically execute instantaneously 137 00:09:38,470 --> 00:09:39,910 and our AI is going to mess up. 138 00:09:39,910 --> 00:09:45,040 So thankfully, inside of our humanoid there is an event called Move to Finished Fires. 139 00:09:45,040 --> 00:09:49,060 When the humanoid finishes walking to a goal declared by Humanoid move two. 140 00:09:49,060 --> 00:09:54,490 So we're going to wait for this event to fire before we move on to the next waypoint. 141 00:09:55,230 --> 00:09:59,790 Now, to make this easier to visualize, we can go ahead and loop through every single waypoint inside 142 00:09:59,790 --> 00:10:05,160 of our path and create a part to represent the position of that waypoint like you saw in the beginning 143 00:10:05,160 --> 00:10:05,970 of the lecture. 144 00:10:05,970 --> 00:10:10,500 So I'm going to again loop through every single point and pass a get waypoints. 145 00:10:10,800 --> 00:10:12,330 And I'm going to create a new part. 146 00:10:12,330 --> 00:10:20,280 So instance dot new part I'm going to set the shape of my part equal to the enum dot part type dot ball. 147 00:10:20,640 --> 00:10:24,870 We can set the size equal to a new vector three of 111. 148 00:10:25,290 --> 00:10:30,990 We'll set the color equal to a new color three and I'll just make it a bright green. 149 00:10:31,900 --> 00:10:37,720 We'll set the material equal to the enum dot material, dot neon, and then we'll make sure to anchor 150 00:10:37,720 --> 00:10:38,530 our part. 151 00:10:38,560 --> 00:10:41,380 We'll make sure can collide is set to false. 152 00:10:41,530 --> 00:10:45,910 And then we'll update the position to be equal to this waypoints position. 153 00:10:45,910 --> 00:10:49,240 And then we can set the parent equal to the workspace. 154 00:10:50,100 --> 00:10:57,060 So now when this code executes, it's going to compute a path for our rig to reach our goal position. 155 00:10:57,060 --> 00:11:00,540 And if it's successful then we're going to walk to each one of those waypoints. 156 00:11:00,540 --> 00:11:04,830 And we should see a part to visualize each one of those waypoint positions. 157 00:11:04,830 --> 00:11:09,180 So let's go ahead and run our game and see what our AI does. 158 00:11:09,180 --> 00:11:10,590 So if I hit run here. 159 00:11:11,500 --> 00:11:13,540 As you can see, our humanoid is moving. 160 00:11:13,540 --> 00:11:15,130 He jumps and then he's going to jump again. 161 00:11:15,130 --> 00:11:17,530 And now he has reached his final destination. 162 00:11:17,530 --> 00:11:22,810 So here you can see each of the individual waypoints that was generated for our humanoid to walk along. 163 00:11:22,810 --> 00:11:28,210 And as you can also tell, the distance between these two waypoints are on average about four studs 164 00:11:28,210 --> 00:11:28,810 apart. 165 00:11:28,810 --> 00:11:34,630 Of course, there are a couple of other waypoints that are set a little bit closer, and that's because 166 00:11:34,630 --> 00:11:38,530 you're not able to space this one four studs away from this other one. 167 00:11:38,530 --> 00:11:40,300 Otherwise you're going to be falling down. 168 00:11:40,300 --> 00:11:44,170 And this is the waypoint right here where it's telling us, hey, we got to jump or else we're going 169 00:11:44,170 --> 00:11:44,530 to fall. 170 00:11:44,530 --> 00:11:46,480 So it forces our humanoid to jump. 171 00:11:46,480 --> 00:11:50,680 And then it forces our humanoid to jump again and we reach our final destination. 172 00:11:51,460 --> 00:11:57,100 Now something very cool we can go ahead and take a look at, is that our AI is going to avoid walking 173 00:11:57,100 --> 00:12:02,770 on these two parts, and that's because this one has a pathfinding modifier inside of it, and this 174 00:12:02,770 --> 00:12:04,270 one is set to Cracked Lava. 175 00:12:04,270 --> 00:12:09,760 And if you remember, we set the cost of this material and this part to be huge. 176 00:12:09,760 --> 00:12:12,850 So our AI should avoid walking on these two parts. 177 00:12:12,850 --> 00:12:14,200 So if I run my game. 178 00:12:14,850 --> 00:12:20,340 As you can see, my eye is avoiding those two ramps, and he's going around and taking the long way 179 00:12:20,340 --> 00:12:22,320 to reach our destination. 180 00:12:22,740 --> 00:12:28,170 However, something I can go ahead and do is I can set the agent can climb property equal to true. 181 00:12:28,170 --> 00:12:32,100 And now if we run our game, our humanoid should instead. 182 00:12:32,100 --> 00:12:37,050 As you can see, he's going to our truss, he's climbing to it and now he's at the waypoint. 183 00:12:37,050 --> 00:12:43,950 So the pathfinding service is always going to calculate the shortest possible path to reach a particular 184 00:12:43,950 --> 00:12:45,150 desired position. 185 00:12:45,150 --> 00:12:52,020 And then we can go ahead and alter the pathing of the pathfinding service based on these pathfinding 186 00:12:52,020 --> 00:12:56,580 modifiers, as well as setting the costs for different materials. 187 00:12:56,580 --> 00:13:04,740 Now, if I set the cost of cracked lava to be a value of like ten, but I were to set the cost of plastic 188 00:13:04,740 --> 00:13:07,320 to be equal to 15. 189 00:13:07,320 --> 00:13:08,730 Well, now. 190 00:13:09,430 --> 00:13:10,000 My. 191 00:13:10,000 --> 00:13:18,610 I should go and walk along this lava because it costs more to pathfind on this plastic than it does 192 00:13:18,610 --> 00:13:19,570 on the lava. 193 00:13:19,570 --> 00:13:24,220 Plus, this plastic is farther away from my humanoid to walk onto it. 194 00:13:24,220 --> 00:13:25,630 So our pathfinding. 195 00:13:25,630 --> 00:13:29,230 I should make a path along this lava ramp and reach our destination. 196 00:13:29,230 --> 00:13:30,280 So let's go ahead and try it out. 197 00:13:30,280 --> 00:13:31,330 If we run. 198 00:13:31,750 --> 00:13:33,550 As you can see, our AI calculated. 199 00:13:33,550 --> 00:13:36,640 Hey, the cost for this particular material wasn't that high. 200 00:13:36,640 --> 00:13:38,770 So let's go ahead and pathfind on to it. 201 00:13:38,950 --> 00:13:48,100 Now, if I set the cost a lot higher, then our AI should instead decide to go and pathfind on to this 202 00:13:48,100 --> 00:13:49,120 truss instead. 203 00:13:49,120 --> 00:13:55,690 So if I set the value of cracked lava to something like 500, then our AI is like, nope, we're not 204 00:13:55,690 --> 00:13:57,340 going to walk on cracked lava. 205 00:13:57,340 --> 00:14:00,550 Instead, we're going to go and climb up our truss part instead. 206 00:14:01,980 --> 00:14:07,860 Though the pathfinding service gives us a lot of options to tweak how we want our rigs in our game to 207 00:14:07,860 --> 00:14:13,260 pathfind to certain areas, the service can be incredibly fun and useful to use. 208 00:14:13,290 --> 00:14:16,020 Anyways, that's all I have for you in this lecture. 209 00:14:16,020 --> 00:14:18,090 I'll see you in the next one.